<template>
    <!-- 
    传入：
        title： el-popover标题
        width：el-popover宽度
        trigger：el-popover宽度触发方式
        placement：el-popover宽度触发方式悬停位置
        treeData：el-tree数据
        nodeKey： el-tree唯一字段
        defaultProps：el-tree props配置
        defaultExpandedKeys：默认展开项
        defaultCheckedKeys：默认选中项
        multiple：是否多选
        showInp：是否显示关键字搜索
        isSelectAll：是否显示勾选全部按钮
    传出：
        multipleChange：el-tree多选情况下数据改变时触发事件
        radioChange：el-tree单选情况下数据改变触发事件
        searchEvt：关键字查询确认触发事件 
    -->
    <el-popover
        :placement="props.placement"
        :title="props.title"
        :width="props.width"
        :trigger="props.trigger"
    >
        <template #default>
            <el-input
                v-if="showInp"
                style="margin-bottom: 15px;"
                v-model="keyContent"
                clearable
                placeholder="请输入关键字查询"
            >
                <template #append>
                    <el-button :icon="Search" @click="emits('searchEvt', keyContent)"/>
                </template>
            </el-input>
            <el-button v-if="props.isSelectAll" style="width: 100%; margin-bottom: 15px;" type="primary" @click="status == true ? selectAll() : invertSelection()">{{!status ? '取消' : ''}}全选</el-button>
            <div>
                <el-tree
                    style="width: 100%"
                    ref="tree"
                    :data="props.treeData"
                    :show-checkbox="multiple"
                    @node-click="nodeClickEvt"
                    :node-key="props.nodeKey"
                    :default-expanded-keys="defaultExpandedKeys"
                    :default-checked-keys="defaultCheckedKeys"
                    :props="props.defaultProps"
                    @check-change="checkChange"
                >
                <template #default="{ node, data }">
                    <span class="custom-tree-node">
                      <el-icon :style="{color: selectObj.id == data.id ? 'red' : ''}"><TrendCharts /></el-icon>
                      <span>{{ node[defaultProps.label] }}</span>
                    </span>
                </template>
                </el-tree>
            </div>
        </template>
        <template #reference>
          <slot></slot>
        </template>
    </el-popover>
</template>

<script setup lang="ts">
import {defineProps, ref, defineEmits} from 'vue'
import { Search } from '@element-plus/icons-vue'
const props = defineProps({
    title: {
        type: String,
        default: '',
        required: false
    },
    width: {
        type: Number,
        default: '',
        required: false
    },
    trigger: {
        type: String,
        default: 'click',
        required: false
    },
    placement: {
        type: String,
        default: 'bottom',
        required: false
    },
    treeData: {
        type: Array,
        default: [],
        required: true
    },
    nodeKey: {
        type: String,
        default: 'id',
        required: false
    },
    defaultProps: {
        type: Object,
        default: {children: 'children', label: 'label'},
        required: false
    },
    defaultExpandedKeys: {
        type: Array,
        default: [],
        required: false
    },
    defaultCheckedKeys: {
        type: Array,
        default: [],
        required: false
    },
    multiple: {
        type: Boolean,
        default: true,
        required: false
    },
    showInp: {
        type: Boolean,
        default: true,
        required: false
    },
    isSelectAll: {
        type: Boolean,
        default: false, 
        required: false
    }
})

// 全选还是单选
const status = ref(true)

// tree组件
const tree = ref(null)

// 注册事件
const emits = defineEmits(['multipleChange', 'radioChange', 'searchEvt'])

// el-tree选择的数据
const selectList = ref([])

// el-tree单选数据
const selectObj = ref({})

// 关键字查询
const keyContent:string = ref('')

// tree复选框改变
const checkChange = (data, checked, indeterminate) => {  
    if (checked) {  
        // 节点被选中  
        getSelectedChildIds(data);  
        selectList.value = selectList.value.concat(getSelectedChildIds(data))
        // 去重
        selectList.value = selectList.value.filter((item, index) => {  
            return selectList.value.findIndex(t => t.id === item.id) === index;  
        });  
        console.log(selectList.value)

    } else {  
        // 节点被取消选中  
        if(data.children) return
        delSelectedChildIds(data)
        console.log(selectList.value)
    }  

    emits('multipleChange', selectList.value)
} 

//  tree复选框改变新增
const getSelectedChildIds = (node) =>  {  
    // 遍历节点及其所有子节点，收集 ID  
    const ids = [];  
    const traverse = (node) => {
        if (node.children) {  
            node.children.forEach((child) => {  
                if(child.children && child.children.length > 0) {
                    traverse(child); // 递归遍历子节点  
                } else {
                    let index = selectList.value.findIndex(it => it.id == child.id)
                    if(index == -1) {
                        ids.push(child);
                    } else {
                    }
                }
            });  
        } else {
            let index = selectList.value.findIndex(it => it.id == node.id)
            if(index != -1) {
                ids.push(node);
            } else {
            }
        }  
    };  
    traverse(node);
    return ids  
} 

//  tree复选框改变删除
const delSelectedChildIds = (node) => {
    // 遍历节点及其所有子节点，收集 ID  
    const ids = [];  
    const traverse = (node) => {
        if (node.children && node.children.length > 0) {  
            node.children.forEach((child) => {  
                if(child.children && child.children.length > 0) {
                    traverse(child); // 递归遍历子节点  
                } else {
                    let index = selectList.value.forEach(it => it.id == child.id)
                    selectList.value.splice(index, 1)
                }
            });  
        } else {
            let index = selectList.value.findIndex(it => it.id == node.id)
            selectList.value.splice(index, 1)
        }  
    };  
    traverse(node);
}

// 节点被点击事件
const nodeClickEvt = (node) => {
    selectObj.value = node
    if(node.hasOwnProperty('children')) return
    emits('radioChange', node)
}

// 获取tree所有节点
const getAllNodes = (data, result = []) => {  
    data.forEach(node => {  
    result.push(node);  
    if (node.children) {  
        getAllNodes(node.children, result);  
    }  
    });  
    return result;  
};  

// 取消全选
const invertSelection = () => {  
    const allNodes = getAllNodes(props.treeData);  
    allNodes.forEach(node => {  
    node.checked = false;  
    });  
    tree.value.setCheckedNodes([]);  
    status.value = true
};  

// 全选
const selectAll = () => {  
    const allNodes = getAllNodes(props.treeData);  
    allNodes.forEach(node => {  
    node.checked = true;  
    });  
    tree.value.setCheckedNodes(allNodes);  
    status.value = false
}


</script>